frontend/pages/e/[uuid]/details.tsx (view raw)
1import moment from 'moment';
2import Button from '@mui/material/Button';
3import Box from '@mui/material/Box';
4import Link from '@mui/material/Link';
5import Paper from '@mui/material/Paper';
6import Container from '@mui/material/Container';
7import TextField from '@mui/material/TextField';
8import Typography from '@mui/material/Typography';
9import {useTheme} from '@mui/material/styles';
10import {DatePicker} from '@mui/x-date-pickers/DatePicker';
11import {PropsWithChildren, useState} from 'react';
12import {useTranslation} from 'react-i18next';
13import pageUtils from '../../../lib/pageUtils';
14import ShareEvent from '../../../containers/ShareEvent';
15import useEventStore from '../../../stores/useEventStore';
16import useToastStore from '../../../stores/useToastStore';
17import useSettings from '../../../hooks/useSettings';
18import EventLayout, {TabComponent} from '../../../layouts/Event';
19import {
20 EventByUuidDocument,
21 useUpdateEventMutation,
22} from '../../../generated/graphql';
23import SupportCaroster from '../../../containers/SupportCaroster';
24
25interface Props {
26 eventUUID: string;
27 announcement?: string;
28}
29
30const Page = (props: PropsWithChildren<Props>) => {
31 return <EventLayout {...props} Tab={DetailsTab} />;
32};
33
34const DetailsTab: TabComponent = ({}) => {
35 const {t} = useTranslation();
36 const theme = useTheme();
37 const settings = useSettings();
38 const [updateEvent] = useUpdateEventMutation();
39 const addToast = useToastStore(s => s.addToast);
40 const setEventUpdate = useEventStore(s => s.setEventUpdate);
41 const event = useEventStore(s => s.event);
42 const [isEditing, setIsEditing] = useState(false);
43 const idPrefix = isEditing ? 'EditEvent' : 'Event';
44
45 const onSave = async e => {
46 try {
47 const {uuid, ...data} = event;
48 const {id, travels, waitingPassengers, __typename, ...input} = data;
49 await updateEvent({
50 variables: {uuid, eventUpdate: input},
51 refetchQueries: ['eventByUUID'],
52 });
53 setIsEditing(false);
54 } catch (error) {
55 console.error(error);
56 addToast(t('event.errors.cant_update'));
57 }
58 };
59 const sectionSx = {
60 marginBottom: theme.spacing(2),
61 width: '540px',
62 maxWidth: '100%',
63 paddingX: theme.spacing(2),
64 };
65
66 const modifyButton = isEditing ? (
67 <Button
68 variant="contained"
69 color="primary"
70 sx={{position: 'absolute', right: theme.spacing(2)}}
71 onClick={onSave}
72 >
73 {t('event.details.save')}
74 </Button>
75 ) : (
76 <Button
77 variant="text"
78 color="primary"
79 sx={{position: 'absolute', right: theme.spacing(2)}}
80 onClick={() => setIsEditing(true)}
81 >
82 {t('event.details.modify')}
83 </Button>
84 );
85
86 if (!event) return null;
87
88 return (
89 <Box
90 sx={{
91 position: 'relative',
92 paddingLeft: '80px',
93
94 [theme.breakpoints.down('md')]: {
95 paddingLeft: 0,
96 paddingBottom: '80px',
97 },
98 }}
99 >
100 <Container maxWidth="sm" sx={{marginTop: theme.spacing(6)}}>
101 <Paper sx={{position: 'relative', padding: theme.spacing(2)}}>
102 {modifyButton}
103 <Box sx={sectionSx}>
104 <Typography variant="h6">{t('event.fields.name')}</Typography>
105 {isEditing ? (
106 <TextField
107 fullWidth
108 value={event.name}
109 onChange={e => setEventUpdate({name: e.target.value})}
110 name="name"
111 id="EditEventName"
112 />
113 ) : (
114 <Typography variant="body1" id={`${idPrefix}Name`}>
115 {event.name ?? t('event.fields.empty')}
116 </Typography>
117 )}
118 </Box>
119 <Box sx={sectionSx}>
120 <Typography variant="h6">{t('event.fields.date')}</Typography>
121 {isEditing ? (
122 <DatePicker
123 renderInput={props => (
124 <TextField
125 {...props}
126 id={`${idPrefix}Date`}
127 fullWidth
128 placeholder={t('event.fields.date_placeholder')}
129 />
130 )}
131 inputFormat="DD/MM/yyyy"
132 value={event.date}
133 onChange={date =>
134 setEventUpdate({
135 date: !date ? null : moment(date).format('YYYY-MM-DD'),
136 })
137 }
138 />
139 ) : (
140 <Typography variant="body1" id={`${idPrefix}Date`}>
141 {event.date
142 ? moment(event.date).format('DD/MM/YYYY')
143 : t('event.fields.empty')}
144 </Typography>
145 )}
146 </Box>
147 <Box sx={sectionSx}>
148 <Typography variant="h6">{t('event.fields.address')}</Typography>
149 {isEditing ? (
150 <TextField
151 fullWidth
152 multiline
153 maxRows={4}
154 inputProps={{maxLength: 250}}
155 helperText={`${event.address?.length ?? 0}/250`}
156 value={event.address}
157 onChange={e => setEventUpdate({address: e.target.value})}
158 id={`${idPrefix}Address`}
159 name="address"
160 />
161 ) : (
162 <Typography variant="body1" id={`${idPrefix}Address`}>
163 {event.address ? (
164 <Link
165 target="_blank"
166 rel="noreferrer"
167 href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(
168 event.address
169 )}`}
170 onClick={e => e.preventDefault}
171 >
172 {event.address}
173 </Link>
174 ) : (
175 t('event.fields.empty')
176 )}
177 </Typography>
178 )}
179 </Box>
180 <Box sx={sectionSx}>
181 <Typography variant="h6">
182 {t('event.fields.description')}
183 </Typography>
184 {isEditing ? (
185 <TextField
186 fullWidth
187 multiline
188 maxRows={4}
189 inputProps={{maxLength: 250}}
190 helperText={`${event.description?.length || 0}/250`}
191 value={event.description || ''}
192 onChange={e => setEventUpdate({description: e.target.value})}
193 id={`${idPrefix}Description`}
194 name="description"
195 />
196 ) : (
197 <Typography variant="body1" id={`${idPrefix}Description`}>
198 {event.description ?? t('event.fields.empty')}
199 </Typography>
200 )}
201 </Box>
202 <Box sx={sectionSx}>
203 <Typography variant="h6">{t('event.fields.link')}</Typography>
204 <Typography>{t('event.fields.link_desc')}</Typography>
205 </Box>
206 <Box pt={4} pb={2} justifyContent="center" display="flex">
207 <ShareEvent title={`Caroster ${event.name}`} />{' '}
208 </Box>
209 </Paper>
210 <Box mt={4} display="flex" justifyContent="center">
211 <SupportCaroster />
212 </Box>
213 </Container>
214 </Box>
215 );
216};
217
218export const getServerSideProps = pageUtils.getServerSideProps(
219 async (context, apolloClient) => {
220 const {uuid} = context.query;
221 const {host = ''} = context.req.headers;
222 let event = null;
223
224 // Fetch event
225 try {
226 const {data} = await apolloClient.query({
227 query: EventByUuidDocument,
228 variables: {uuid},
229 });
230 event = data?.eventByUUID?.data;
231 } catch (error) {
232 return {
233 notFound: true,
234 };
235 }
236
237 return {
238 props: {
239 eventUUID: uuid,
240 metas: {
241 title: event?.attributes?.name || '',
242 url: `https://${host}${context.resolvedUrl}`,
243 },
244 },
245 };
246 }
247);
248export default Page;